﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Xml.Linq;
using ThreeByte.ActiveDeck.Controls;
using ThreeByte.Media;
using ThreeByte.ActiveDeck.Config;
using System.Windows.Data;
using System.Windows;
using ThreeByte.Converters;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.IO;
using System.Windows.Documents;

namespace ThreeByte.ActiveDeck.AddIn.Content.Controls
{
    public class DesignerButton : DesignerControl
    {
        public GraphicResource ImageOn {
            get;
            set;
        }

        public GraphicResource ImageOff {
            get;
            set;
        }

        //public static readonly DependencyProperty ActionProperty = DependencyProperty.Register("Action",
        //    typeof(NavigationAction), typeof(DesignerButton), new PropertyMetadata(OnActionChanged));

        private NavigationAction _action;
        public NavigationAction Action {
            get {
                return _action;
            }
            set {
                _action = value;
                NotifyPropertyChanged("Action");
            }
        }

        private List<NavigationAction> _additionalActions = new List<NavigationAction>();
        public List<NavigationAction> AdditionalActions {
            get {
                return _additionalActions;
            }
        }
 
        public DesignerButton(GraphicResource imageOff, PixelSpace pos)
            : base(pos) {

                ImageOff = imageOff;
                CoreConfig currentConfig = Globals.ThisAddIn.GetCurrentConfig();
                Color overlayColor = currentConfig.DefaultButtonOverlayColor;
                ImageOn = CreateShadedImage(imageOff, overlayColor);
        }

        public DesignerButton(XElement node, Dictionary<Guid, GraphicResource> resources) {
            try {
                //Get the Position/Size
                int top = int.Parse(node.Attribute("Top").Value);
                int left = int.Parse(node.Attribute("Left").Value);
                int width = int.Parse(node.Attribute("Width").Value);
                int height = int.Parse(node.Attribute("Height").Value);

                foreach(XElement actionNode in node.Elements(ns + "Action")) {
                    if(Action != null) {
                        Action = NavigationAction.FromXml(actionNode);
                    } else {
                        AdditionalActions.Add(NavigationAction.FromXml(actionNode));
                    }
                }

                //Get the images
                XElement imageOnNode = node.Element(ns + "ImageOn");
                ImageOn = resources[Guid.Parse(imageOnNode.Attribute("ResourceID").Value)];
                XElement imageOffNode = node.Element(ns + "ImageOff");
                ImageOff = resources[Guid.Parse(imageOffNode.Attribute("ResourceID").Value)];

                //Update this object
                DefaultPixelSpace = new PixelSpace() { W = 768, H = 1024, X = 0, Y = 0 };
                CurrentPixelSpace = new PixelSpace() { X = left, Y = top, W = width, H = height };
            } catch(Exception ex) {
                throw ex;
            }
        }

        public override XElement ToXml() {
            XElement node = base.ToXml();

            node.Add(PixelSpaceAsAttributes(CurrentPixelSpace));
            if(Action != null) {
                node.Add(Action.ToXml());
            }
            foreach(NavigationAction a in AdditionalActions) {
                node.Add(a.ToXml());
            }

            XElement imageOnNode = new XElement(ns + "ImageOn", new XAttribute("ResourceID", ImageOn.ID));
            node.Add(imageOnNode);
            XElement imageOffNode = new XElement(ns + "ImageOff", new XAttribute("ResourceID", ImageOff.ID));
            node.Add(imageOffNode);
            return node;
        }

        public override XElement GetPresentationXml(PixelTranslator translation = null) {
            XElement node = new XElement(ns + "Button");
            PixelSpace pos = CurrentPixelSpace;
            if(translation != null) {
                pos = translation.Translate(pos);
            }
            node.Add(PixelSpaceAsAttributes(pos));
            if(!string.IsNullOrWhiteSpace(Condition)) {
                node.Add(new XAttribute("Condition", Condition));
            }

            if(Action != null) {
                //TODO: This is a temporary fix up
                if(Action.Jump && (Action.Section == 0)) {
                    //Find out the section number and populate it
                    Action.Section = Globals.ThisAddIn.GetCurrentConfig().GetSectionForPageId(Action.Page);
                }
                node.Add(Action.ToXml());
            }
            foreach(NavigationAction a in AdditionalActions) {
                if(a.Jump && (a.Section == 0)) {
                    //Find out the section number and populate it
                    a.Section = Globals.ThisAddIn.GetCurrentConfig().GetSectionForPageId(a.Page);
                }
                node.Add(a.ToXml());
            }

            XElement imageOnNode = new XElement(ns + "ImageOn", new XAttribute("ResourceID", ImageOn.ID));
            node.Add(imageOnNode);

            XElement imageOffNode = new XElement(ns + "ImageOff", new XAttribute("ResourceID", ImageOff.ID));
            node.Add(imageOffNode);

            return node;
        }

        public override List<GraphicResource> GetGraphicResources() {
            List<GraphicResource> resources = base.GetGraphicResources();
            resources.Add(ImageOn);
            resources.Add(ImageOff);
            return resources;
        }


        public static GraphicResource CreateShadedImage(GraphicResource imageIn, Color overlayColor) {

            //Create a new Grid
            Grid rootGrid = new Grid();

            Size targetSize = new Size(imageIn.Image.PixelWidth, imageIn.Image.PixelHeight);

            //Add an Image
            rootGrid.Children.Add(new Image() { Source = imageIn.Image });
            //Add an overlay layer
            Border overlay = new Border() { Background = new SolidColorBrush(overlayColor), BorderThickness = new Thickness(0) };
            overlay.OpacityMask = new ImageBrush(imageIn.Image);
            rootGrid.Children.Add(overlay);
            
            //TODO: Are all these steps necessary?
            rootGrid.Measure(targetSize);
            rootGrid.Arrange(new Rect(targetSize));
            rootGrid.UpdateLayout();

            //Render it out to the desired size
            BitmapSource targetBitmap = ImageUtil.SaveToBitmapSource(rootGrid, targetSize);
            return new GraphicResource(targetBitmap, string.Format("{0}_Inactive", (imageIn.Name ?? "Image")), ImageType.PNG);
        }

        public static DesignerButton CreateFromImageFile(string path, Point insertAt = default(Point)) {

            using(FileStream fs = new FileStream(path, FileMode.Open)) {
                BitmapImage newBitmap = new BitmapImage();
                newBitmap.BeginInit();
                newBitmap.CacheOption = BitmapCacheOption.OnLoad;
                newBitmap.StreamSource = fs;
                newBitmap.EndInit();
                newBitmap.Freeze();

                Image newImage = new Image();
                GraphicResource newResource = new GraphicResource(newBitmap, "DragDrop", ImageType.PNG);
                newImage.Source = newResource.Image;

                insertAt.X = Math.Max(0, insertAt.X - (newResource.Image.PixelWidth / 2));
                insertAt.Y = Math.Max(0, insertAt.Y - (newResource.Image.PixelHeight / 2));

                PixelSpace pos = new PixelSpace() { H = (int)(newResource.Image.PixelHeight), W = (int)(newResource.Image.PixelWidth), X = (int)(insertAt.X), Y = (int)(insertAt.Y) };
                return new DesignerButton(newResource, pos);
            }
        }
    }
}
